﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cspl.AnimalFight.Lib;
using Cspl.AnimalFight.Lib.Data;
using Cspl.AnimalFight.Lib.EventHandlers;
using System.Text.RegularExpressions;

namespace Cspl.AnimalFight.Main
{
    public class Program
    {
        private static BattleField battleField;

        public static void Main(string[] args)
        {
            //init
            battleField = new BattleField();
            ModifyAnimal modify = new ModifyAnimal();

            #region Init Default Animals

            Dog dog1 = new Dog
            {
                Name = "DOGGY",
                HP = 1000,
                DP = 100,
                AP = 300,
                Mood = DogMood.Good
            };

            Dog dog2 = new Dog
            {
                Name = "SNOOPY",
                HP = 1000,
                DP = 150,
                AP = 250,
                Mood = DogMood.Bad
            };

            Duck duck1 = new Duck
            {
                Name = "DONAL",
                HP = 1000,
                DP = 200,
                AP = 500,
            };

            Snake snake1 = new Snake
            {
                Name = "SNAKE",
                HP = 1000,
                DP = 50,
                AP = 300,
            };

            Horse horse1 = new Horse
            {
                Name = "MAKIBAO",
                HP = 1000,
                DP = 200,
                AP = 200,
            };

            battleField[dog1.Name] = dog1;
            battleField[dog2.Name] = dog2;
            battleField[snake1.Name] = snake1;
            battleField[horse1.Name] = horse1;
            battleField[duck1.Name] = duck1;

            #endregion

            initMainMenu();

            string optStr;
            int opt;
            string commandLine;
            string command;

            do
            {
                try
                {
                    //menu
                    bool isValid = false;
                    do
                    {
                        //repeated until option input is valid
                        Console.WriteLine("\nMAIN MENU :");
                        Console.WriteLine("1.Battle");
                        Console.WriteLine("2.Manage Animal");
                        Console.WriteLine("3.Exit The Application");
                        Console.Write("\nInput your option (1-3) : ");

                        optStr = Console.ReadLine();
                        isValid = isValidOption(optStr);
                        if (!isValid)
                        {
                            Console.WriteLine("\n{0} IS NOT A VALID OPTION!!!\n", optStr);
                        }

                    } while (!isValid);

                    opt = modify.ConvertStringToInt(optStr);
                    
                    switch (opt)
                    {
                        case 1:     //option to enter battle field
                            Console.Clear();
                            printSign("     BATTLE FIELD     ");

                            Console.WriteLine("\nList of animals :");
                            foreach (AnimalBase animal in battleField.AnimalList)
                            {
                                animal.print();
                            }
                            
                            commandLine = string.Empty;
                            command = string.Empty;
                            
                            while (command != "EXIT")
                            {
                                Console.WriteLine("\n-. command attack and eat : [attack/eat] [animal_name] [target_name]");
                                Console.WriteLine("-. command defend, escape, and enter : [defend/escape/enter] [animal_name]");
                                Console.WriteLine("-. command for exit: [exit]");
                                Console.Write("\nInput your command : ");
                                
                                //convert commands to uppercase to handle in-case-sensitive string input
                                commandLine = System.Console.ReadLine().ToUpper();
                                
                                //split commandLine into array of commands (to get command and arguments)
                                string[] commands = commandLine.Split(' ');

                                //Handling bad input for command
                                command = commands[0];
                                switch (command)
                                {
                                    case "ATTACK":
                                        if (commands.Length < 3 || commands.Length > 3)
                                        {
                                            Console.WriteLine("Invalid command for ATTACK.");
                                        }
                                        else
                                        {
                                            if (!isValidAnimal(commands[1]))
                                            {
                                                Console.WriteLine("Animal {0} is not valid.", commands[1]);
                                            }
                                            else if (!isValidAnimal(commands[2]))
                                            {
                                                Console.WriteLine("Animal {0} is not valid.", commands[2]);
                                            }
                                            else
                                            {
                                                battleField.Command(commands[1], Commands.Attack, commands[2]);
                                            }
                                        }
                                        break;

                                    case "DEFEND":
                                        if (commands.Length < 2 || commands.Length > 2)
                                        {
                                            Console.WriteLine("Invalid command for DEFEND.");
                                        }
                                        else
                                        {
                                            if (!isValidAnimal(commands[1]))
                                            {
                                                Console.WriteLine("Animal {0} is not valid.", commands[1]);
                                            }
                                            else
                                            {
                                                battleField.Command(commands[1], Commands.Defend, string.Empty);
                                            }
                                        }
                                        break;

                                    case "ESCAPE":
                                        if (commands.Length < 2 || commands.Length > 2)
                                        {
                                            Console.WriteLine("Invalid command for ESCAPE.");
                                        }
                                        else
                                        {
                                            if (!isValidAnimal(commands[1]))
                                            {
                                                Console.WriteLine("Animal {0} is not valid.", commands[1]);
                                            }
                                            else
                                            {
                                                battleField.Command(commands[1], Commands.Escape, string.Empty);
                                            }
                                        }
                                        break;

                                    case "ENTER":
                                        if (commands.Length < 2 || commands.Length > 2)
                                        {
                                            Console.WriteLine("Invalid command for ENTER.");
                                        }
                                        else
                                        {
                                            if (!isValidAnimal(commands[1]))
                                            {
                                                Console.WriteLine("Animal {0} is not valid.", commands[1]);
                                            }
                                            else
                                            {
                                                battleField.Command(commands[1], Commands.Enter, string.Empty);
                                            }
                                        }
                                        break;

                                    case "EAT":
                                        if (commands.Length < 3 || commands.Length > 3)
                                        {
                                            Console.WriteLine("Invalid command for EAT.");
                                        }
                                        else
                                        {
                                            if (!isValidAnimal(commands[1]))
                                            {
                                                Console.WriteLine("Animal {0} is not valid.", commands[1]);
                                            }
                                            if (!isValidAnimal(commands[2]))
                                            {
                                                Console.WriteLine("Animal {0} is not valid.", commands[2]);
                                            }
                                            else
                                            {
                                                battleField.Command(commands[1], Commands.Eat, commands[2]);
                                            }
                                        }
                                        break;

                                    case "EXIT":
                                        Console.WriteLine("Back To Main Menu.");
                                        initMainMenu();
                                        break;

                                    default:
                                        Console.WriteLine("Invalid command.");
                                        break;
                                }
                            }
                            break;

                        case 2 :        //option for animal management
                            commandLine = string.Empty;
                            command = string.Empty;

                            while (command != "EXIT")
                            {
                                Console.Clear();
                                printSign("     ANIMAL MANAGEMENT     ");

                                Console.WriteLine("\nList of animals :");
                                foreach (AnimalBase animal in battleField.AnimalList)
                                {
                                    animal.print();
                                }

                                Console.WriteLine("\n-. Type 'add' to add new animal.");
                                Console.WriteLine("-. Type 'delete <animal_name>' to delete animal.");
                                Console.WriteLine("-. Type 'exit' to go back to main menu.");

                                Console.Write("\nInput your command : ");
                                
                                //convert commands to uppercase to handle in-case-sensitive string input
                                commandLine = System.Console.ReadLine().ToUpper();
                                
                                string[] commands = commandLine.Split(' ');

                                //Handling bad input for command
                                command = commands[0];
                                switch (command)
                                {
                                    case "ADD":     //add new animal
                                        Console.Clear();
                                        printSign("     ADD NEW ANIMAL     ");

                                        //add new animal
                                        BattleField.NewAnimal newAnimal = new BattleField.NewAnimal();                        
                                        try
                                        {
                                            Console.Write("\nAnimal Type(1.Dog, 2.Duck, 3.Snake, 4.Horse) :");
                                            int type = modify.ConvertStringToInt(Console.ReadLine());

                                            if (!(type >= 1 && type <= 4))
                                            {
                                                Console.WriteLine("invalid animal type");
                                                break;
                                            }
                                            else
                                            {
                                                newAnimal.type = (Animals)type;
                                            }
                                            Console.Write("Name : ");
                                            string newName = modify.checkAnimalName((Console.ReadLine()).ToUpper());
                                            Console.Write("Health Power : ");
                                            int newHP = modify.ConvertStringToInt(Console.ReadLine());
                                            Console.Write("Defense Power : "); ;
                                            int newDP = modify.ConvertStringToInt(Console.ReadLine());
                                            Console.Write("Attack Power : ");
                                            int newAP = modify.ConvertStringToInt(Console.ReadLine());
                                            newAnimal.name = newName;
                                            newAnimal.HP = newHP;
                                            newAnimal.DP = newDP;
                                            newAnimal.AP = newAP;

                                            if (type == 1)
                                            {
                                                Console.Write("Mood (1.Bad, 2.Good) : ");
                                                int moodId = modify.ConvertStringToInt(Console.ReadLine());
                                                DogMood mood;
                                                if (moodId == 1)
                                                {
                                                    mood = DogMood.Bad;
                                                }
                                                else
                                                {
                                                    mood = DogMood.Good;
                                                }
                                                newAnimal.mood = mood;
                                            }
                                            modify.addAnimal(newAnimal, battleField);
                                        }
                                        catch (Exception ex)
                                        {                            
                                            break;
                                        }
                                        break;

                                    case "DELETE":      //delete animal
                                        if (commands.Length < 2 || commands.Length > 2)
                                        {
                                            Console.WriteLine("Invalid command for delete animal.");
                                        }
                                        else
                                        {
                                            if (!isValidAnimal(commands[1]))
                                            {
                                                Console.WriteLine("Animal {0} is not valid.", commands[1]);
                                            }
                                            else
                                            {
                                                battleField.DeleteAnimal(commands[1]);
                                            }
                                        }
                                        break;

                                    case "EXIT":
                                        Console.WriteLine("Back To Main Menu.");
                                        initMainMenu();
                                        break;

                                    default:
                                        Console.WriteLine("Invalid command.");
                                        break;
                                }
                            }   
                            break;

                        case 3:     //option for exiting the application
                            Console.WriteLine("exit the application");
                            break;

                        default:
                            Console.WriteLine("Invalid option");
                            break;
                    }
                }                   
                catch (Exception)
                {
                    break;
                }
            } while (opt != 3);
        }

        //initialize main menu
        //display welcome sign and animal information
        private static void initMainMenu()
        {
            Console.Clear();

            string message = "  WELCOME TO THE ANIMAL FIGHTING GROUPONE V1.0  ";
            printSign(message);

            Console.WriteLine("\nList of animals :");
            foreach (AnimalBase animal in battleField.AnimalList)
            {
                animal.print();
            }
        }

        //print string message in a box display
        private static void printSign(string message)
        {
            var encoder = System.Text.Encoding.GetEncoding(437);

            var topLeft = new byte[] { 201 };
            var topRight = new byte[] { 187 };
            var botLeft = new byte[] { 200 };
            var botRight = new byte[] { 188 };
            var horizontal = new byte[] { 205 };
            var vertical = new byte[] { 186 };
            var blank = new byte[] { 32 };

            Console.Write(encoder.GetString(topLeft));
            for (int i = 0; i < message.Length; i++)
            {
                Console.Write(encoder.GetString(horizontal));
            }
            Console.WriteLine(encoder.GetString(topRight));

            Console.Write(encoder.GetString(vertical));
            for (int i = 0; i < message.Length; i++)
            {
                Console.Write(encoder.GetString(blank));
            }
            Console.WriteLine(encoder.GetString(vertical));

            Console.WriteLine(encoder.GetString(vertical) + message + encoder.GetString(vertical));

            Console.Write(encoder.GetString(vertical));
            for (int i = 0; i < message.Length; i++)
            {
                Console.Write(encoder.GetString(blank));
            }
            Console.WriteLine(encoder.GetString(vertical));

            Console.Write(encoder.GetString(botLeft));
            for (int i = 0; i < message.Length; i++)
            {
                Console.Write(encoder.GetString(horizontal));
            }
            Console.WriteLine(encoder.GetString(botRight));
        }

        //to validate input of main menu option
        private static bool isValidOption(string str)
        {
            Regex regex = new Regex("^[1-3]{1}$");
            return regex.IsMatch(str);
        }

        //to check whether an animalName is valid as an AnimalBase
        private static bool isValidAnimal(string animalName)
        {
            bool isValid = false;

            foreach (AnimalBase a in battleField.AnimalList)
            {
                if (a.Name.Equals(animalName))
                {
                    isValid = true;
                    break;
                }
            }

            return isValid;
        }

    }

}
